package com.newgoldcurrency.utils;
import com.google.gson.JsonParser;
import com.newgoldcurrency.App;
import com.newgoldcurrency.BuildConfig;

import org.json.JSONObject;

import java.nio.charset.StandardCharsets;

import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.DelimiterBasedFrameDecoder;
import io.netty.handler.codec.string.StringEncoder;

public class NettyClient {
    private static ChannelHandlerContext ctx;
    private final NettyCallback callback;
    public NettyClient(NettyCallback callback) {
        this.callback = callback;
    }
    public String convertByteBufToString(ByteBuf buf) {
        String str;
        if(buf.hasArray()) { // 处理堆缓冲区
            str = new String(buf.array(), buf.arrayOffset() + buf.readerIndex(), buf.readableBytes());
        } else { // 处理直接缓冲区以及复合缓冲区
            byte[] bytes = new byte[buf.readableBytes()];
            buf.getBytes(buf.readerIndex(), bytes);
            str = new String(bytes, 0, buf.readableBytes());
        }
        return str;
    }
    public void start(String jiemian) {
        if (Tools.isWifiProxy()){
            Tools.toast("Network malicious agent is detected and all network requests are terminated");
        }else {
            Bootstrap b = new Bootstrap();
            b.group(new NioEventLoopGroup()).channel(NioSocketChannel.class).handler(new ChannelInitializer<SocketChannel>() {
                @Override
                protected void initChannel(SocketChannel ch) {
                    ch.pipeline().addLast(new DelimiterBasedFrameDecoder(1024 * 1024 * 1024, Unpooled.copiedBuffer("@!@#@".getBytes())));
                    ch.pipeline().addLast(new StringEncoder(StandardCharsets.UTF_8));
                    ch.pipeline().addLast(new ChannelInboundHandlerAdapter() {
                        @Override
                        public void channelInactive(ChannelHandlerContext ctx) {
                            ctx.close();
                        }
                        @Override
                        public void channelRead(ChannelHandlerContext ctx, Object msg) {
                            ByteBuf byteBuf = (ByteBuf) msg;
                            String str=convertByteBufToString(byteBuf);
                            callback.back(JsonParser.parseString( str).getAsJsonObject());
                        }
                        @Override
                        public void channelActive(ChannelHandlerContext ctx) throws Exception {
                            NettyClient.ctx = ctx;
                            JSONObject jsonObject = new JSONObject();
                            jsonObject.put("cmd", "CONNECT");
                            jsonObject.put("user_id", App.userBean.id);
                            jsonObject.put("type", jiemian);
                            byte[] data = jsonObject.toString().getBytes(StandardCharsets.UTF_8);
                            byte[] sign = "@!@#@".getBytes(StandardCharsets.UTF_8);
                            byte[] send = new byte[data.length + sign.length];
                            System.arraycopy(data, 0, send, 0, data.length);
                            System.arraycopy(sign, 0, send, data.length, sign.length);
                            ctx.channel().writeAndFlush(new String(send, StandardCharsets.UTF_8));
                        }

                        @Override
                        public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
                            cause.printStackTrace();
                        }
                    });
                }
            });
            try {
                ChannelFuture f = b.connect(BuildConfig.TCP_DOMAIN, BuildConfig.TCP_PORT).sync();
                f.addListener((ChannelFutureListener) arg0 -> {
                    if (!f.isSuccess()) f.cause().printStackTrace();
                });
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    public void close() {
        if (ctx != null && ctx.channel().isOpen()) ctx.channel().close();
    }
    public void sendMsg(JSONObject jo) {
        if (ctx == null) {
            Tools.toast("connect err!");
        } else {
            byte[] data = jo.toString().getBytes(StandardCharsets.UTF_8);
            byte[] sign = "@!@#@".getBytes(StandardCharsets.UTF_8);
            byte[] send = new byte[data.length + sign.length];
            System.arraycopy(data, 0, send, 0, data.length);
            System.arraycopy(sign, 0, send, data.length, sign.length);
            ctx.channel().writeAndFlush(new String(send, StandardCharsets.UTF_8));
        }
    }
}